/***************************************************************
|	File:		Player.h
|	Author:		
|	Course:		
|	Purpose:	
***************************************************************/

#pragma once

#include "BaseObject.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "GrappleGun.h"
#include "Arrow.h"
#include <vector>

// Check n'th bit		x & (1<<n)
// Set n'th bit			x | (1<<n)
// Unset n'th bit		x &~(1<<n)
// Toggle n'th bit		x ^ (1<<n)


class SGD::Point;

class Player : public BaseObject
{
public:

	Player();
	~Player();
	
	virtual void Render(void)				override;
	virtual void Update(float elapsedTime)	override;
	virtual SGD::Rectangle GetRect(void) const	override;

	SGD::Vector		GetVelocity()	const			{ return m_vtVelocity;		}
	float			GetPotMod()		const			{ return m_fPotionMod;		}
	bool			IsSliding()		const			{ return m_bIsSliding;		}
	SGD::Size		GetScale()		const			{ return m_szScale;			}
	SGD::Point		GetPrevPos()	const			{ return m_ptPreviousPos;	}
	unsigned char	GetChecks()		const			{ return checks;			}
	Arrow*			GetArrow()		const			{ return m_Arrow;			}	
	GrappleGun*		GetGrapGun()	const			{ return m_pGrapGun;		}	
	bool			GetDeathPot()	const			{ return m_bHasNoDeathPotion; }
	bool			GetGrounded()	const			{ return m_bGrounded; }


	void			SetPotionMod(float potmod)		{ m_fPotionMod = potmod;	}
	void			SetVelocity(SGD::Vector vel)	{ m_vtVelocity = vel;		}
	void			SetGrapGun(GrappleGun* gun)		{ m_pGrapGun = gun;			}
	void			SetChecks(unsigned int ch)		{ checks = ch;				}
	void			ForceToSlide()					{ (m_szScale.width < 0.0f ? m_bSlidingL = true : m_bIsSliding = true); }
	void			SetImageSize(SGD::Size sz)		{ m_szImageSize = sz; }


	virtual void	HandleCollision	(  BaseObject* pOther )	override;
	void			GrappleHookMath();

	void			Reset();

	//Helper Functions
	void Accel();
	void Input(float dt);
	void Dash(float dt);
	void Slide();
	void SlideReset();
	void Stomp();
	void Phase(float dt);
private:

	SGD::Rectangle Cell(unsigned char cell);

	//misc
	float	m_fPotionMod;				// Potion modifier
	bool	m_bGrounded;				// Is the player grounded? Used to prevent double jumping
	bool	m_HasScissors;				// Does the player have scissors?
	bool	m_bJumped;
	bool	m_bGrapActive;
	bool	m_bHasNoFricPotion;
	SGD::Vector m_vtNoFricVelocity;
	unsigned char  cell;


	bool	m_bHasNoDeathPotion;

	//Player movement attricbutes
	float	m_fFriction;				// Players friction
	float	m_fMoveSpeed;				// Max Move Speed
	float	m_fAccelRate;				// Acceleration Rate
	float	m_fJumpForce;				// Jump force
	float	m_fGravity;					// Gravity
	float	m_fDashSpeed;

	//slidding
	bool	m_bIsSliding;				// Is the Player Sliding?
	bool	m_bSlidingL;				// Is the player facing left while sliding?

	//Dashing
	float	m_fDashTimer;				// Timer used for dashing distance, and dashing delay
	bool	m_bDash;					// Is the player dashing?
	
	//Phaseing
	float	m_fPhaseTimer = 1.0f;
	bool    m_bHasPhase;
	bool	m_bCanPhase;
	bool	m_bIsPhasing;

	//stomping
	bool	m_bStomp;					// Is the player Stomping
	bool	m_bPrevSlide;				// Was I sliding?

	// Timers
	float	m_fRespawnTimer;
	float	m_fPotionTimer;
	float	m_fAnimationTimer;

	//Fan Death
	bool	m_bFanDeath;

	
	
	//Acid Death
	bool	m_bAcidDeath;

	//Tesla/Wire shocked
	bool	m_bShocked;

	//Camera Offset
	float m_fCameraOff;

	enum {GRAPPLE,BOOTS,PHASE,SCISSORS};
	unsigned char checks;

	//Points to check if grounded
	std::vector<SGD::Point>		m_vtFourCorners;

	SGD::Point		m_ptPreviousPos;

	SGD::Vector		m_vtGrappleVelocity;
	SGD::Vector		m_vtVelocity = SGD::Vector(0, 0);		//Velocity
	SGD::Size		m_szScale	 = SGD::Size(1, 1);			//Scale
	SGD::Size		m_szImageSize;

	GrappleGun*		m_pGrapGun = nullptr;
	Arrow*			m_Arrow;

	SGD::HAudio		m_aDeath;
	SGD::HAudio		m_aStomp;

	float			m_fPrevPad;
};